package utils

import (
	"crypto/rand"
	"encoding/hex"
	"regexp"
	"strings"
	"time"
)

// 标准时间格式
const (
	StandardTimeFormat = "2006-01-02 15:04:05"
	DateFormat         = "2006-01-02"
	TimeFormat         = "15:04:05"
)

// FormatTime 将时间格式化为标准格式
func FormatTime(t time.Time) string {
	if t.IsZero() {
		return ""
	}
	return t.Format(StandardTimeFormat)
}

// FormatDate 将时间格式化为日期格式
func FormatDate(t time.Time) string {
	return t.Format(DateFormat)
}

// FormatTimeOnly 将时间格式化为时间格式
func FormatTimeOnly(t time.Time) string {
	return t.Format(TimeFormat)
}

// ParseTime 将字符串解析为时间对象
func ParseTime(timeStr string) (time.Time, error) {
	if timeStr == "" {
		return time.Time{}, nil
	}
	return time.Parse(StandardTimeFormat, timeStr)
}

// ParseDate 将日期字符串解析为时间对象
func ParseDate(s string) (time.Time, error) {
	return time.Parse(DateFormat, s)
}

// Now 获取当前时间的标准格式
func Now() string {
	return FormatTime(time.Now())
}

// NowDate 获取当前日期的标准格式
func NowDate() string {
	return FormatDate(time.Now())
}

// IsToday 判断时间是否为今天
func IsToday(t time.Time) bool {
	now := time.Now()
	return t.Year() == now.Year() && t.Month() == now.Month() && t.Day() == now.Day()
}

// AddDays 添加天数
func AddDays(t time.Time, days int) time.Time {
	return t.AddDate(0, 0, days)
}

// DiffDays 计算两个时间之间的天数差
func DiffDays(t1, t2 time.Time) int {
	// 将时间规范化为当天的0点
	t1 = time.Date(t1.Year(), t1.Month(), t1.Day(), 0, 0, 0, 0, t1.Location())
	t2 = time.Date(t2.Year(), t2.Month(), t2.Day(), 0, 0, 0, 0, t2.Location())

	// 计算相差的小时数并转换为天
	hours := t2.Sub(t1).Hours()
	return int(hours / 24)
}

// NewJSONTime 返回当前时间的JSONTime
func NewJSONTime() JSONTime {
	return JSONTime(time.Now())
}

// TimeToJSONTime 将time.Time转换为JSONTime
func TimeToJSONTime(t time.Time) JSONTime {
	return JSONTime(t)
}

// FormatTimeWithLayout 使用指定布局格式化时间
func FormatTimeWithLayout(t time.Time, layout string) string {
	if t.IsZero() {
		return ""
	}
	return t.Format(layout)
}

// ParseTimeWithLayout 使用指定布局解析时间字符串
func ParseTimeWithLayout(timeStr, layout string) (time.Time, error) {
	if timeStr == "" {
		return time.Time{}, nil
	}
	return time.Parse(layout, timeStr)
}

// DateAdd 日期加上指定天数
func DateAdd(t time.Time, days int) time.Time {
	return t.AddDate(0, 0, days)
}

// DateSub 计算两个日期之间的天数差
func DateSub(t1, t2 time.Time) int {
	duration := t1.Sub(t2)
	return int(duration.Hours() / 24)
}

// StartOfDay 获取某一天的开始时间
func StartOfDay(t time.Time) time.Time {
	year, month, day := t.Date()
	return time.Date(year, month, day, 0, 0, 0, 0, t.Location())
}

// EndOfDay 获取某一天的结束时间
func EndOfDay(t time.Time) time.Time {
	year, month, day := t.Date()
	return time.Date(year, month, day, 23, 59, 59, 999999999, t.Location())
}

// StartOfMonth 获取某一月的开始时间
func StartOfMonth(t time.Time) time.Time {
	year, month, _ := t.Date()
	return time.Date(year, month, 1, 0, 0, 0, 0, t.Location())
}

// EndOfMonth 获取某一月的结束时间
func EndOfMonth(t time.Time) time.Time {
	year, month, _ := t.Date()
	lastDay := time.Date(year, month+1, 0, 23, 59, 59, 999999999, t.Location())
	return lastDay
}

// Slugify 将字符串转换为URL友好的slug
func Slugify(s string) string {
	// 转小写
	s = strings.ToLower(s)

	// 移除非字母数字字符
	reg := regexp.MustCompile("[^a-z0-9\\s-]")
	s = reg.ReplaceAllString(s, "")

	// 替换空格为横线
	s = regexp.MustCompile("\\s+").ReplaceAllString(s, "-")

	// 替换多个横线为一个横线
	s = regexp.MustCompile("-+").ReplaceAllString(s, "-")

	// 去除首尾横线
	s = strings.Trim(s, "-")

	return s
}

// RandomString 生成指定长度的随机字符串
func RandomString(length int) string {
	if length <= 0 {
		return ""
	}

	// 计算需要生成的字节数（每个字节可以生成2个十六进制字符）
	bytes := make([]byte, (length+1)/2)

	// 填充随机数据
	rand.Read(bytes)

	// 转换为十六进制字符串并截取所需长度
	return hex.EncodeToString(bytes)[:length]
}
